package com.wonders.framework.util.bean;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.BeanUtils;

import com.wonders.framework.entity.vo.Page;
import com.wonders.framework.exception.FrameworkException;

/**
 * 对象工具
 * 
 * @author WuBin
 * 
 */
public class BeanUtil {

	/**
	 * 拷贝属性
	 * 
	 * @param source
	 *            源
	 * @param target
	 *            目标
	 * @param ignoreNull
	 *            是否忽略空值
	 * @param ignoreProps
	 *            忽略属性
	 */
	private static void copyProperties(Object source, Object target,
			boolean ignoreNull, String... ignoreProps) {
		PropertyDescriptor[] targetPds = BeanUtils
				.getPropertyDescriptors(target.getClass());
		List ignoreList = null;
		if (ignoreProps != null) {
			ignoreList = Arrays.asList(ignoreProps);
		}
		for (int i = 0; i < targetPds.length; i++) {
			PropertyDescriptor targetPd = targetPds[i];
			if (targetPd.getWriteMethod() != null
					&& (ignoreList == null || !ignoreList.contains(targetPd
							.getName()))) {
				PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(
						source.getClass(), targetPd.getName());
				if (sourcePd != null && sourcePd.getReadMethod() != null) {
					try {
						Method getter = sourcePd.getReadMethod();
						if (!Modifier.isPublic(getter.getDeclaringClass()
								.getModifiers())) {
							getter.setAccessible(true);
						}
						Object value = getter.invoke(source, new Object[0]);
						if (ignoreNull && value == null)
							continue;
						Method setter = targetPd.getWriteMethod();
						if (!Modifier.isPublic(setter.getDeclaringClass()
								.getModifiers())) {
							setter.setAccessible(true);
						}
						setter.invoke(target, new Object[] { value });
					} catch (Exception e) {
						throw new FrameworkException("属性拷贝失败", e);
					}
				}
			}
		}
	}

	/**
	 * 拷贝属性
	 * 
	 * @param source
	 *            源
	 * @param target
	 *            目标
	 * @param ignoreProps
	 *            忽略属性
	 */
	public static void copyProperties(Object source, Object target,
			String... ignoreProps) {
		try {
			copyProperties(source, target, true, ignoreProps);
		} catch (Exception e) {
			throw new FrameworkException("实体转换失败", e);
		}
	}

	/**
	 * 拷贝属性
	 * 
	 * @param source
	 *            源
	 * @param target
	 *            目标
	 */
	public static void copyProperties(Object source, Object target) {
		try {
			copyProperties(source, target, true);
		} catch (Exception e) {
			throw new FrameworkException("实体转换失败", e);
		}
	}

	/**
	 * 拷贝属性
	 * 
	 * @param <T>
	 * @param source
	 *            源
	 * @param clazz
	 *            目标类
	 * @return 目标实体
	 */
	public static <T extends Object> T copyProperties(Object source,
			Class<T> clazz) {
		if (source == null) {
			return null;
		}
		T target = null;
		try {
			target = clazz.newInstance();
		} catch (Exception ex) {
			throw new FrameworkException("创建实体失败", ex);
		}
		try {
			copyProperties(source, target, true);
		} catch (Exception e) {
			throw new FrameworkException("实体转换失败", e);
		}
		return target;
	}

	/**
	 * 拷贝列表
	 * 
	 * @param <T>
	 * @param source
	 *            源
	 * @param clazz
	 *            目标类
	 * @return 目标列表实体
	 */
	public static <T extends Object> List<T> copyList(List source,
			Class<T> clazz) {
		if (source == null) {
			return null;
		}
		List<T> list = new ArrayList<T>();
		for (Object object : source) {
			list.add(copyProperties(object, clazz));
		}
		return list;
	}

	/**
	 * 拷贝分页
	 * 
	 * @param <T>
	 * @param source
	 *            源
	 * @param clazz
	 *            目标类
	 * @return 目标分页实体
	 */
	public static <T extends Object> Page copyPage(Page source, Class<T> clazz) {
		if (source == null) {
			return null;
		}
		source.setData(copyList(source.getData(), clazz));
		return source;
	}

}
